
package at.fhj.ase.clientarch.common.util;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author cja, sfe | www.fh-joanneum.at | Client Architectures and Design
 */
public final class EncryptorUtil {
  private final static Logger logger = LoggerFactory.getLogger(EncryptorUtil.class);
  
  /* 
   * Classes from outside shall know which techniques are used within the class, but not be allowed to use the instances as e.g.
   * the messageDigest instance as access shall be controlled solely by this class 
   */
  public final static String HASH_ALGORITHM = "MD5";
  private final static MessageDigest MESSAGE_DIGEST_MD5;

  /* 
   * Classes from outside shall know which techniques are used within the class, but not be allowed to use the instances as e.g.
   * the charset instance as access shall be controlled solely by this class 
   */
  public final static String CHARSET = "UTF-8";
  private final static Charset CHARSET_UTF8;

  static {
    try {
      MESSAGE_DIGEST_MD5 = MessageDigest.getInstance(HASH_ALGORITHM);
      CHARSET_UTF8 = Charset.forName(CHARSET);
    } catch (NoSuchAlgorithmException e) {
      // should never be the case, but to be sure...
      final String LOG_MSG = "Could not instantiate MD5 message digest";
      logger.error(LOG_MSG);
      throw new IllegalArgumentException(LOG_MSG);
    }
  }

  private EncryptorUtil() {
    throw new AssertionError("EncryptorUtil: Util classes are not intended/allowed to be instantiated!");
  }

  /**
   * @param data the bytes that shall be hashed with the MD5 algorithm
   * @return the hased bytes or the provided bytes if an exception occured.
   */
  public static byte[] toMD5(final byte[] data) {
    MESSAGE_DIGEST_MD5.update(data);
    return MESSAGE_DIGEST_MD5.digest();
  }

  /** Convenience method calling {@link EncryptorUtil#toMD5(byte[])} after convertion to byte-array */
  public static byte[] toMD5(final String data) {
    return toMD5(data.getBytes());
  }

  /** Convenience method calling {@link EncryptorUtil#toMD5(byte[])} after convertion to byte-array */
  public static byte[] toMD5(final char[] data) {
    return toMD5(String.valueOf(data).getBytes());
  }

  /** Returns the binary data in a <strong>new</strong> string instance. */
  public static String toString(final byte[] data) {
    return new String(data, CHARSET_UTF8);
  }
}
